package cc.shacocloud.luanniao.web.controller

import cc.shacocloud.luanniao.core.service.UserService
import cc.shacocloud.luanniao.web.controller.interceptor.NotLoggedUserAuth
import cc.shacocloud.luanniao.web.controller.interceptor.UserAuth
import cc.shacocloud.luanniao.web.model.dto.input.LoginInput
import cc.shacocloud.luanniao.web.model.mo.UserSessionMo
import cc.shacocloud.luanniao.web.service.SessionService
import org.springframework.validation.BeanPropertyBindingResult
import org.springframework.validation.BindException
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.server.ServerWebExchange
import java.util.*

/**
 * 登录控制器
 * @author 思追(shaco)
 */
@Validated
@RestController
class LoginController(
    val sessionService: SessionService,
    val userService: UserService,
) {

    /**
     * 登录接口
     */
    @NotLoggedUserAuth
    @PostMapping("/api/login")
    suspend fun login(
        @Validated @RequestBody input: LoginInput,
        exchange: ServerWebExchange,
    ) {
        val bindingResult = BeanPropertyBindingResult(input, "input")

        val userPo = userService.findByUsername(input.username)
        if (userPo == null) {
            bindingResult.rejectValue("username", "用户不存在")
            throw BindException(bindingResult)
        }

        if (!userService.matchesPassword(input.password, userPo.password)) {
            bindingResult.rejectValue("password", "密码无效")
            throw BindException(bindingResult)
        }

        sessionService.saveSession(exchange.response, UserSessionMo(UUID.randomUUID().toString(), userPo))
    }

    /**
     * 登出
     */
    @UserAuth
    @DeleteMapping("/api/login-out")
    suspend fun loginOut(exchange: ServerWebExchange) {
        val session = sessionService.getUserSession(exchange)
        sessionService.removeSession(exchange.response, session)
    }


}